home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
edit
/
pt20pc.zip
/
BUFFERS.C
< prev
next >
Wrap
Text File
|
1991-02-04
|
10KB
|
355 lines
#include "pt.h"
#include "memory.h"
#define hashFn(x,y,z) ((13*(x)+(int)((y)&0x7FFF))%(z))
void pascal
/* XTAG:unlink1 */
unlink1(bp)
register struct diskBuffer *bp;
{
extern struct diskBuffer *bufHash[];
int h2;
/* unlink it from its old hash chain */
if( bp->forwardHash != NULL )
bp->forwardHash->backwardHash = bp->backwardHash;
if( bp->backwardHash != NULL )
bp->backwardHash->forwardHash = bp->forwardHash;
else { /* first in the hash chain */
h2 = hashFn(bp->handle, bp->blockNumber, NBUFHASH);
bufHash[h2] = bp->forwardHash;
}
}
struct diskBuffer * pascal
/* XTAG:getBuffer */
getBuffer(handle, blockNumber)
int handle;
long blockNumber;
{
extern unsigned char msgBuffer[];
extern struct diskBuffer *buffers;
extern struct diskBuffer *bufHash[];
extern int nextBuffer;
extern struct openFile *files;
extern int nBuffers;
extern struct SREGS segRegs;
extern int addHandle;
extern int debug;
extern int maxFiles;
extern unsigned char *userMessages[];
register int i;
register struct diskBuffer *bp;
int h;
unsigned char far *fp;
unsigned int bufferBits, fileBits;
/* see if the block is already in a buffer */
h = hashFn(handle, blockNumber, NBUFHASH);
bp = bufHash[h];
while( bp != NULL ) {
if( bp->handle==handle && bp->blockNumber==blockNumber ) {
break;
}
bp = bp->forwardHash;
}
if( bp == NULL ) {
/* if not, assign it a buffer and fill it with data */
/* LATER: use LRU buffer replacment instead of FIFO */
if( ++nextBuffer >= nBuffers )
nextBuffer = 0;
bp = &buffers[nextBuffer];
if( bp->handle != -1 ) { /* is the buffer in use? */
/* unlink it from its old hash chain */
unlink1(bp);
/* Invalidate any possible buffer caches. */
bufferBits = ((unsigned int)FP_OFF(bp->bufferAddress))
>> BUFFERSHIFT;
for(i = 0; i < maxFiles; i++) {
/* get the high order bits of the offset */
/* of the buffer address */
fileBits =
((unsigned int)files[i].logBufOffset)
>> BUFFERSHIFT;
/* see if the offsets match */
if( bufferBits == fileBits ) {
/* if so invalidate the cache */
files[i].hiLogBuffer = -1L;
}
}
/* write the buffer out to disk */
if( bp->written ) {
lseekls(bp->handle,
(bp->blockNumber)<<BUFFERSHIFT, 0);
i = writeFar(bp->handle, bp->bufferAddress,
BUFFERSIZE);
if( i < BUFFERSIZE )
msg(userMessages[FULLMSG], 3);
}
}
bp->handle = handle;
bp->blockNumber = blockNumber;
bp->written = 0;
/* read in the new buffer contents */
lseekls(handle, blockNumber<<BUFFERSHIFT, 0);
i = readFar(handle, bp->bufferAddress, BUFFERSIZE);
/* read zeros for non-existing chararacters */
/* this will occur in the add file only */
if( i <= 0 ) {
if( i < 0 ) {
sprintf(msgBuffer,
"getBuffer: read error, ret=%d, handle=%d", i, handle);
msg(msgBuffer, 3);
}
/* zero out the buffer */
fp = bp->bufferAddress;
for(i = 0; i < BUFFERSIZE; ++i)
*fp++ = '\0';
}
bp->backwardHash = NULL;
bp->forwardHash = bufHash[h];
if( bufHash[h] != NULL )
bufHash[h]->backwardHash = bp;
bufHash[h] = bp;
}
return bp;
}
void pascal
/* XTAG:fidInvalid */
fidInvalid(fid)
int fid;
{
extern struct diskBuffer *buffers;
extern int nBuffers;
extern struct changeItem *change;
extern int tailChange, nextChange;
register int i;
/* invalidate the buffer cache */
for(i = 0; i < nBuffers; i++)
if( buffers[i].handle == fid ) {
unlink1(&buffers[i]);
buffers[i].handle = -1;
}
/* invalidate and history changes that refer to this file */
i = tailChange;
if( i != nextChange ) { /* make sure the history is not empty */
while( 1 ) {
if( change[i].fileId==fid && change[i].type!=CNULL) {
freePieces( change[i].firstPiece );
change[i].type = CNULL;
}
if( i == nextChange )
break;
if( ++i >= NHISTORY )
i = 0;
}
}
}
unsigned char pascal
/* XTAG:readChar */
readChar(fileId, logicalByte)
int fileId;
long logicalByte;
{
int n;
unsigned char far *firstByte;
unsigned char far *dummy;
n = getSpan(fileId, logicalByte, &firstByte, &dummy, 0);
if( n != 0 )
return '\0';
else
return *firstByte;
}
int pascal
/* XTAG:getSpan */
getSpan(fileId, logicalByte, inFirstByte, inLastByte, reversed)
int fileId, reversed;
long logicalByte;
unsigned char far * *inFirstByte;
unsigned char far * *inLastByte;
{
extern unsigned char msgBuffer[];
extern struct openFile *files;
extern int debug;
extern int addHandle;
extern struct SREGS segRegs;
register struct openFile *ff;
struct diskBuffer *buf;
long physicalByte, blockNumber, nn, bp;
int handle;
long offset;
struct piece *pp;
struct longPointer *firstByte;
struct longPointer *lastByte;
/* for efficiency, keep some addresses */
ff = &files[fileId];
firstByte = (struct longPointer *)inFirstByte;
lastByte = (struct longPointer *)inLastByte;
/* if file is not open print an error message */
if( fileId == -1 || ff->origHandle == -1 ) {
sprintf(msgBuffer, "getSpan: file %d is not open", fileId);
msg(msgBuffer, 3);
return 1;
}
/* see if the logical byte number is invalid */
if( logicalByte < 0 || logicalByte >= ff->fileSize)
return 1;
/* check for optimized special cases */
if( ff->loLogBuffer<=logicalByte && logicalByte<=ff->hiLogBuffer ) {
/* if this logical byte is in the buffer cache then set up */
/* the addresses using the saved segment and offset fields */
firstByte->offset = ff->logBufOffset
+ (unsigned int)(logicalByte - ff->loLogBuffer);
if( reversed ) {
lastByte->offset = firstByte->offset;
firstByte->offset = ff->logBufOffset;
} else
lastByte->offset = ff->logBufOffset
+ (unsigned int)(ff->hiLogBuffer - ff->loLogBuffer);
firstByte->segment = ff->logBufSegment;
lastByte->segment = ff->logBufSegment;
return 0;
}
/* see if we already know what piece it is in */
/* findPiece checks this but for speed we do it here anyway */
/* since readChar is on the critical path of performance */
if( ff->loLogPiece<=logicalByte && logicalByte<=ff->hiLogPiece ) {
pp = ff->logPiece;
physicalByte = pp->position + logicalByte - ff->loLogPiece;
} else {
pp = findPiece(logicalByte, ff, &nn);
physicalByte = pp->position + logicalByte - nn;
/* remember this piece as the cached piece */
ff->logPiece = pp;
ff->loLogPiece = nn;
ff->hiLogPiece = nn + pp->length - 1;
}
/* get the physical file block containing this character */
blockNumber = physicalByte>>BUFFERSHIFT;
/* figure out the appropriate handle */
if( pp->file == ORIGFILE )
handle = ff->origHandle;
else /* pp->file == ADDFILE */
handle = addHandle;
/* get the buffer that this character is in */
buf = getBuffer(handle, blockNumber);
/* figure out how many bytes into the buffer logicalByte is */
offset = physicalByte - (blockNumber<<BUFFERSHIFT);
firstByte->offset = (char *)FP_OFF(buf->bufferAddress) + offset;
firstByte->segment = (char *)FP_SEG(buf->bufferAddress);
/* Remember the logical byte limits in this buffer. */
/* Is the beginning of the buffer still in this piece? */
bp = logicalByte - offset;
/* bp = logical byte number of the first physical byte in buffer */
/* "buf" ASSUMING all of this buffer is in piece "pp". Now we */
/* check this assumption and adjust things if it is false */
if( bp >= ff->loLogPiece ) {
/* the first byte in this buffer is still in the piece */
ff->loLogBuffer = bp;
ff->logBufSegment = (char *)FP_SEG(buf->bufferAddress);
ff->logBufOffset = (char *)FP_OFF(buf->bufferAddress);
} else {
/* the piece begins inside the buffer */
ff->loLogBuffer = ff->loLogPiece;
ff->logBufSegment = (char *)FP_SEG(buf->bufferAddress);
ff->logBufOffset = (char *)FP_OFF(buf->bufferAddress)
+ (ff->loLogPiece - bp);
}
/* Now check if the last physical byte in this buffer is still */
/* in piece "pp" */
/* bp: